/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2013 All Rights Reserved.
 */
package com.pingan.mobilegw.core.service.support.groovy;

import groovy.lang.GroovyClassLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ClassUtils;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Groovy脚本工厂
 * 
 * @author jiadao
 * @version $Id: GroovyScriptFactory.java, v 0.1 2013-7-16 下午4:59:03 jiadao Exp $
 */
public class GroovyScriptFactory {

    /** 日志logger */
    private static final Log logger                = LogFactory.getLog(GroovyScriptFactory.class);

    /** Groovy类加载器 */
    private static GroovyClassLoader            groovyClassLoader     = new GroovyClassLoader(
                                                                          ClassUtils
                                                                              .getDefaultClassLoader());        ;
    /** GroovyProcessor缓存 */
    private static Map<String, GroovyProcessor> cacheGroovyProcessors = new HashMap<String, GroovyProcessor>();

    /** 执行线程池 */
    private static Executor                     executor              = Executors
                                                                          .newFixedThreadPool(1);

    /**
     * 获取缓存的GroovyProcessor列表
     * 
     * @return
     */
    public static Collection<GroovyProcessor> getGroovyProcessors() {

        return cacheGroovyProcessors.values();
    }

    /**
     * 注册脚本
     * 
     * @param groovyScriptFiles
     */
    public synchronized static void register(List<String> groovyScriptFiles) {

        try {
            // 加载生成
            Map<String, GroovyProcessor> newMap = new HashMap<String, GroovyProcessor>();
            for (String script : groovyScriptFiles) {
                // 获取文件
                File file = new File(GroovyConstant.GROOVY_FILE_PATH + script);

                // 校验文件
                if (!validateFile(script, file)) {
                    continue;
                }

                // 执行groovy script
                String scriptText = null;//FileUtils.readFileToString(file, "UTF-8");
                GroovyProcessor processor = executeScript(script, scriptText);
                if (processor != null) {
                    newMap.put(script, processor);
                }
            }
            // 更新缓存
            cacheGroovyProcessors = newMap;
        } catch (Exception e) {
            logger.error("注册groovy脚本失败" + groovyScriptFiles, e);
        }
    }

    /**
     * 校验文件是否存在合法
     * 
     * @param script
     * @param file
     */
    private static boolean validateFile(String script, File file) {
        if (!file.exists()) {
            logger.warn( "加载的groovy脚本【"+script+"】不存在");
            return false;
        }
        if (!file.isFile()) {
            logger.warn( "加载的groovy脚本【"+script+"】不是一个文件");
            return false;
        }
        if (!file.getName().endsWith("groovy")) {
            logger.warn( "加载的groovy脚本【"+script+ "】不是一个groovy脚本");
            return false;
        }
        return true;
    }

    /**
     * 执行脚本
     * 1. 脚本是Runnable脚本，则立即执行
     * 2. 脚本是GroovyProcessor脚本，则返回放入缓存
     * 3. 其他脚本不做处理
     * 
     * @param scriptName
     * @param text
     * @return
     */
    private static GroovyProcessor executeScript(String scriptName, String text) {

        try {
            Class<?> clazz = groovyClassLoader.parseClass(text);
            Object target = clazz.newInstance();
            if (target instanceof Runnable) {
                logger.warn("加载的groovy脚本【"+scriptName+"】是一个groovy可执行的脚本");
                executor.execute((Runnable) target);
                return null;
            } else if (target instanceof GroovyProcessor) {
                logger.warn("加载的groovy脚本【"+ scriptName+"】是一个GroovyProcessor的脚本");
                return (GroovyProcessor) target;
            } else {
                logger.warn("加载的groovy脚本【"+ scriptName+"】不是GroovyProcessor的子类");
                return null;
            }
        } catch (Exception e) {
            logger.error("加载的groovy脚本【"+scriptName+ "】异常", e);
            return null;
        }
    }
}
